/**
 * Created with IntelliJ IDEA.
 * User: zzl
 * Date: 12-11-12
 * To change this template use File | Settings | File Templates.
 */
(function ($, fnName, undefined) {

    var ColResizer = function (table, options) {
        var me = this;
        me.$table = $(table);
        me.options = options;

        //
        var thead = domex.getFirstChildElelement(table, 'THEAD');
        var trInThead = domex.getFirstChildElelement(thead, 'TR');
        var ths = domex.getChildElelements(trInThead, 'TH');
        me.$allThs = $(ths);
        me.updateVisibleThs();

        if (me.options.fixedTableWidth) {
            me.setup();
        }
        else {
            //?
        }
    };

    var proto = { constructor: ColResizer };
    ColResizer.prototype = proto;

    /*todo: call this when column visibility changed*/
    proto.updateVisibleThs = function() {
        var me = this;
        var ths = [];
//        var cols = [];
//        var $allCols = me.$table.children('colgroup').children();
        for (var n = 0; n < me.$allThs.length; n++) {
            var th = me.$allThs[n];
            if (!$(th).hasClass('hidden')) {
                ths.push(th);
//                cols.push($allCols[n]);
            }
        }
        me.$ths = $(ths);
//        me.$cols = $(cols);
    };

    proto.setup = function () {
        var me = this;

        console.log('@@@@@@@@@@@@@@ colResizer setup........ @' + new Date());

        me.$table.off('headerChange.colResizer');
        me.$table.on('headerChange.colResizer', function () {
            me.table_headerChange();
        });

        if (me.$colResizerLayer) {
            me.$colResizerLayer.remove();
        }
        me.$table.addClass('colResizer_table');

        var table = me.$table[0];

        // determine resizerLayer's z-index
        var elem = table;
        while (elem.parentNode != document.body) {
            elem = elem.parentNode;
        }
        var zIndex = (parseInt($(elem).css('z-index')) || 0) + 1;

        var n;
        var $ths = me.$ths;

        var $colResizerLayer = $('<div class="colResizerLayer"></div>').appendTo(document.body);
        me.$colResizerLayer = $colResizerLayer;
        if (me.options.debug) {
            $colResizerLayer.addClass('debug');
        }
        else {
            if ($colResizerLayer.css('background-color') == 'transparent') {
                //make hittestable
                $colResizerLayer.css({
                    backgroundColor: 'white',
                    opacity: 0
                });
            }
        }

        //
        me.$colResizerLayer.on('mouseup', function (e) {
            me.$table[0].focus();
        });

        //
        var tableOffset = {
            left: table.offsetLeft,
            top: table.offsetTop
        };//  me.$table.offset();
        var tableWidth = me.$table.outerWidth();
        var $caption = me.$table.children('caption');
        var y = tableOffset.top;
        if ($caption.length) {
            y += $caption.height();
        }
        $colResizerLayer.css({
            'z-index': zIndex,
            left: tableOffset.left,
            top: y,
            width: tableWidth,
            height: $ths.outerHeight() + parseInt(me.$table.css('border-top-width'))
        });

        //
        var $th, width;

        //
        var flexWidths = tableWidth - $ths.length;
        var lastFlexColIndex;
        for (n = 0; n < $ths.length; n++) {
            $th = $($ths[n]);
            width = $th.data('width');
            if (!width) {
                var $tds = me.$table.find('tr>td:visible:nth-child(' + (n + 1) + ')');
                width = me.getMaxContentWidth($ths[n], $tds);
            }
            if (width > 1) {
                $th.width(width);
                flexWidths -= width;
            }
            else {
                lastFlexColIndex = n;
            }
            flexWidths -= (parseInt($th.css('border-left'))||0) +
                (parseInt($th.css('border-right'))||0) +
                (parseInt($th.css('padding-left'))||0) +
                (parseInt($th.css('padding-right'))||0);
//            else {
//                $th.css('width', (width * 100) + '%');
//            }
        }
        for (n = 0; n < $ths.length; n++) {
            $th = $($ths[n]);
            width = $th.data('width');
            if (n == lastFlexColIndex) {
//                $th.css('width', '100%');
                $th.css('width', '');
            }
            else if (width < 1) {
                $th.width(flexWidths * width);
                $th.width($th.width());
            }
//            $th.width($th.width());
        }
        //
        for (n = 0; n < $ths.length - 1; n++) {
            $th = $($ths[n]);

            var $colResizer = $('<div class="colResizer"></div>').appendTo($colResizerLayer);
            $colResizer.css({
                left: $($ths[n + 1]).offset().left - tableOffset.left - domex.getWidth($colResizer) / 2
            });
            $colResizer.data('index', n);
            $colResizer.data('th', $ths[n]);
            $colResizer.on('mousedown', function (e) {
                me.colResizer_mousedown(e, this);
            });
            $colResizer.on('dblclick', function (e) {
                me.colResizer_dblclick(e, this);
            });
        }

        me.syncResizerPositions();

        me.lastTableWidth = me.$table.width();
    };

    proto.table_headerChange = function () {
        var me = this;
        me.setup();
        var headerVisible = !me.$table.hasClass('hideHeader');
        me.$colResizerLayer.toggle(headerVisible);
    };

    proto.colResizer_dblclick = function (e, colResizer) {
        var me = this;
        e.preventDefault();
        me.activeResizer = colResizer;
        me.downTh = $(me.activeResizer).data('th');
        var index = $(me.activeResizer).data('index');
        var tds = me.$table.find('tr>td:visible:nth-child(' + (index + 1) + ')');
        var width;

        width = parseInt($(me.downTh).attr('data-width'));
        if (width > 1) {
            // fixed
        }
        else {
            width = me.getMaxContentWidth(me.downTh, tds)
        }

        //console.log('##' + width);
        var curWidth = domex.getWidth(me.downTh);
//        alert(curWidth);
        me.offsetHeader(width - curWidth);
        me.syncResizerPositions();
        me.updateWidthDatas();
    };

    proto.getMaxContentWidth = function (th, tds) {
        var maxWidth = th.scrollWidth;
        var scrollWidth;

        for (var n = 0; n < tds.length; n++) {
            var td = tds[n];
            var $td = $(td);
            var $children = $td.children();
            if ($children.length && $children.is('.cell-wrapper')) {
                scrollWidth = $children[0].scrollWidth;
            }
            else {
                scrollWidth = td.scrollWidth;
            }
            if (scrollWidth > maxWidth) {
                maxWidth = scrollWidth;
            }
        }
        return maxWidth;
    };

    proto.colResizer_mousedown = function (e, colResizer) {
        var me = this;
        e.preventDefault();

        me.activeResizer = colResizer;
        $(colResizer).addClass('activeColResizer');
        $(document).on('selectstart.' + fnName, function (e) {
            e.preventDefault();
        });
        $(document).on('mousemove.' + fnName, function (e) {
            me.document_mousemove(e);
        });
        $(document).on('mouseup.' + fnName, function (e) {
            me.document_mouseup(e);
        });

        me.downX = e.pageX;
        me.downTh = $(me.activeResizer).data('th');
        me.downThWidth = domex.getWidth(me.downTh);

        //
        var nextTh;// = $(me.downTh).nextAll(':visible:first');
        var $nextThs = $(me.downTh).nextAll(':visible');
        for (var n = 0; n < $nextThs.length; n++) {
            nextTh = $nextThs[n];
            if (parseFloat($(nextTh).attr('data-width')) < 0) {
                break;
            }
        }
        me.nextTh = nextTh;
        me.nextThWidth = domex.getWidth(nextTh);

        //
        me.downResizerLeft = $(me.activeResizer).position().left;
    };

    proto.document_mousemove = function (e) {
        var me = this;
        var dx = e.pageX - me.downX;
        me.offsetHeader(dx);
        return false;

    };

    proto.document_mouseup = function (e) {
        var me = this;
        me.syncResizerPositions();
        me.updateWidthDatas();
        $(document).off('selectstart.' + fnName);
        $(document).off('mousemove.' + fnName);
        $(document).off('mouseup.' + fnName);
        $(me.activeResizer).removeClass('activeColResizer');
        me.activeResizer = null;

    };

    proto.offsetHeader = function (dx) {
        var me = this;
        if (!dx) {
            return;
        }
        var $colResizer = $(me.activeResizer);
        var index = $colResizer.data('index');

        if (me.downThWidth + dx < 5) {
            dx = -me.downThWidth + 5;
        }
        else if (me.nextThWidth - dx < 5) {
            dx = me.nextThWidth - 5;
        }
        var width = me.downThWidth + dx;
        var nextWidth = me.nextThWidth - dx;

//        console.log('dx: ' + dx + ', width: ' + width + ', nextWidth: ' + nextWidth);

        var $nextTh = $(me.nextTh);
        $nextTh.width(nextWidth);
        $(me.downTh).width(width);

        $colResizer.css('left', me.downResizerLeft + dx);
    };

    proto.syncResizerPositions = function () {
        var me = this;

        var $table = me.$table;
        var $ths = me.$ths;
        var tableOffset = $table.offset();
        var $layer = me.$colResizerLayer;

        var tableWidth = $table.outerWidth();
        $layer.width(tableWidth);

        var $colResizers = $layer.find('div');
        for (var n = 0; n < $ths.length - 1; n++) {
            var th = $ths[n];
            var $colResizer = $($colResizers[n]);
            $colResizer.css({
                left: $($ths[n + 1]).offset().left - tableOffset.left - domex.getWidth($colResizer) / 2
            });
        }
    };

    proto.updateWidthDatas = function () {
        var me = this;
        var $ths = me.$ths;
        var widths = [];
        var flexWidths = 0;
        var width, n;
        for (n = 0; n < $ths.length; n++) {
            var $th = $($ths[n]);
            var dataWidth = parseFloat($th.attr('data-width'));
            if (dataWidth < 1) {
                width = $th.width();
                widths[n] = width;
                flexWidths += width;
            }
            else {
                widths[n] = 0;
            }
        }
        for (n = 0; n < widths.length; n++) {
            width = widths[n];
            if (width) {
                width = width / flexWidths;
                $($ths[n]).data('width', width);
            }
        }
    };

    //
    $.fn.colResizer = $.addPluginFn(fnName, ColResizer, {
        debug: false,
        fixedTableWidth: true
    });


})(jQuery, 'colResizer');